package idv.arthur.work;


import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.tmatesoft.svn.core.ISVNDirEntryHandler;
import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import com.google.gson.Gson;

public class QuerySVN extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private SVNRepository repo;
	private SVNClientManager manager;  
    private SVNURL repositoryBaseUrl; 
    private String fn;
    private String parentDir;
    private String path;
    private ArrayList<DirStruc> dirStrucs = new ArrayList<DirStruc>();
    private Collection logEntries = null;
    private Set changedPathsSet = null;
    private SVNLogEntry logEntry = null;
    private Widgets wid = new Widgets();
    private String subSysId = null;
    public QuerySVN() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	doPost(request,response);
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		dirStrucs.clear();
		
		request.setCharacterEncoding( wid.UIcodeSet );
		response.setContentType("application/json");
		response.setCharacterEncoding( wid.UIcodeSet );		
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		String errPars = "}";
		
		String strSVNpar = "";
		String split = "##";
		fn = request.getParameter("fn");
		String svnPath = request.getParameter("svnPath");
		subSysId = request.getParameter("subSysId");
		
		try {
			conn = wid.getConn(true);
			int fromSysNo = wid.getLocalSysNo(conn, ps, rs);
			int tarSysNo = fromSysNo;
			strSVNpar = wid.getTarSVNConnection(fromSysNo, tarSysNo, conn, ps, rs,split);
			DefaultSVNOptions options = new DefaultSVNOptions();  
	        manager = SVNClientManager.newInstance(options,  strSVNpar.split(split)[0],strSVNpar.split(split)[1]); //如果需要用戶名密碼
	        if ( svnPath == null ){
	        	repositoryBaseUrl = SVNURL.parseURIEncoded(strSVNpar.split(split)[2]+"/"+subSysId); // 傳入svn地址	
	        } else {
	        	repositoryBaseUrl = SVNURL.parseURIEncoded(strSVNpar.split(split)[2]+"/"+subSysId+"/"+svnPath); // 傳入svn地址
	        }
	        
	        repo = SVNRepositoryFactory.create(repositoryBaseUrl);
	        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(strSVNpar.split(split)[0],strSVNpar.split(split)[1]);
	        repo.setAuthenticationManager(authManager);
	        
	        test();
		} catch (SVNException e) { 
			wid.kem(conn, ps, e, "SVNException", true);  
	    } catch (Exception e) { 
			wid.kem(conn, ps, e, wid.toEType("Exception")+errPars, wid.isPrint2Console );  
	    } finally {
			try {
				if (rs != null) {rs.close();}
				if (ps!= null) {ps.close();}
				if (conn!= null) {conn.close();}
			} catch (SQLException e) {
				System.out.println(wid.errProcess(e));
			}
		}
		
		response.getWriter().write(new Gson().toJson(dirStrucs));	
	}
	
	
	private class DirEntryHandler implements ISVNDirEntryHandler {
		private void perf(SVNDirEntry dirEntry)  throws SVNException {
			path = dirEntry.getRelativePath();
			if ( dirEntry.getKind() == SVNNodeKind.FILE  ) {
        		if (!path.contains("/")) {
    				parentDir = "";
    			} else { /*************要改*****************/
    				parentDir = path.substring(0, path.lastIndexOf(dirEntry.getName())-1);
    			}
        		
        		DirStruc ds = new DirStruc();
        		ds.setLastUpdateDate(wid.changeTimeFormat(dirEntry.getDate()));
        		ds.setDir(false);
        		ds.setHome(parentDir);
        		ds.setId(dirEntry.getName().replaceAll("\\.","__"));

        		logEntries = repo.log( new String[] { path } ,null , (long)1 , (long) dirEntry.getRevision() , true , true );
        		ArrayList<Long> verSet = new ArrayList<Long>();
    	        for ( Iterator entries = logEntries.iterator( ); entries.hasNext( ); ) {
    	            logEntry = ( SVNLogEntry ) entries.next( );
    	            if ( logEntry.getChangedPaths( ).size( ) > 0 ) {
    	                changedPathsSet = logEntry.getChangedPaths( ).keySet( );
    	                for ( Iterator changedPaths = changedPathsSet.iterator( ); changedPaths.hasNext( ); ) {
    	                    SVNLogEntryPath entryPath = ( SVNLogEntryPath ) logEntry.getChangedPaths( ).get( changedPaths.next( ) );
    	                    if ( (entryPath.getType()=='A' || entryPath.getType()=='M') && entryPath.getPath( ).indexOf("/"+path)!=-1) {
    	                    	verSet.add( logEntry.getRevision());
    	                    }
    	                }
    	            }
    	        }
    	        ds.setVerSet(verSet);
        		ds.setVer((verSet.size()!=0?(verSet.get(verSet.size()-1)):logEntry.getRevision()));
        		dirStrucs.add(ds);
        	}
		}
		
        public void handleDirEntry(SVNDirEntry dirEntry) throws SVNException {
        	if ("".equalsIgnoreCase(fn.trim())) {
        		perf(dirEntry);
        	} else {
        		if ( fn.equalsIgnoreCase(dirEntry.getName()) ) {
        			perf(dirEntry);	
            	}	
        	}
        }  
    }
	
	private void test() throws SVNException {
		SVNLogClient logClient = manager.getLogClient();
		DirEntryHandler handler = new DirEntryHandler(); // 在svn
		logClient.doList(repositoryBaseUrl, SVNRevision.HEAD, SVNRevision.HEAD,false, true, handler); // 列出當前svn地址的目錄，對每個文件進行處理
	}
	
	
	 class DirStruc {
			boolean isDir;
			ArrayList<Long> verSet;
			long ver;
			String id;
			String home;
			String lastUpdateDate;

			public ArrayList<Long> getVerSet() {
				return verSet;
			}
			public void setVerSet(ArrayList<Long> verSet) {
				this.verSet = verSet;
			}
			public String getLastUpdateDate() {
				return lastUpdateDate;
			}
			public void setLastUpdateDate(String lastUpdateDate) {
				this.lastUpdateDate = lastUpdateDate;
			}
			public boolean isDir() {
				return isDir;
			}
			public void setDir(boolean isDir) {
				this.isDir = isDir;
			}
			public long getVer() {
				return ver;
			}
			public void setVer(long ver) {
				this.ver = ver;
			}
			public String getId() {
				return id;
			}
			public void setId(String id) {
				this.id = id;
			}
			public String getHome() {
				return home;
			}
			public void setHome(String home) {
				this.home = home;
			}
		}
}